package org.dromara.system.service.impl;

import com.github.sd4324530.fastweixin.api.UserAPI;
import com.github.sd4324530.fastweixin.api.entity.UserInfo;
import com.github.sd4324530.fastweixin.api.response.GetUserInfoResponse;
import com.github.sd4324530.fastweixin.api.response.GetUsersResponse;
import lombok.extern.slf4j.Slf4j;
import cn.hutool.core.collection.CollUtil;
import org.dromara.common.core.exception.BusiException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.web.context.ContextHolder;
import org.dromara.system.domain.bo.SysAccountBo;
import org.dromara.system.domain.vo.SysAccountVo;
import org.dromara.system.enums.AppCodeEnum;
import org.dromara.system.service.ISysAccountService;
import org.springframework.stereotype.Service;
import org.dromara.system.domain.bo.SysMemberBo;
import org.dromara.system.domain.vo.SysMemberVo;
import org.dromara.system.domain.SysMember;
import org.dromara.system.mapper.SysMemberMapper;
import org.dromara.system.service.ISysMemberService;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import java.util.*;
import java.util.function.Function;

import static net.sf.jsqlparser.util.validation.metadata.NamedObject.user;

/**
 * 微信用户Service业务层处理
 *
 * @author yilong.fu
 * @date 2024-09-14
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class SysMemberServiceImpl implements ISysMemberService {

    private final SysMemberMapper baseMapper;

    private final ISysAccountService sysAccountService;

    @Override
    @Transactional(readOnly = true)
    public SysMemberVo selectByOpenId(String openId) {
        SysMemberBo ex = new SysMemberBo();
        ex.setOpenId(openId);
        return getOne(ex);
    }


    /**
     * 查询微信用户
     */
    @Override
    @Transactional(readOnly = true)
    public SysMemberVo getOne(SysMemberBo bo, Function<LambdaQueryWrapper<SysMember>, Boolean>
        func) {
        LambdaQueryWrapper<SysMember> lqw = buildQueryWrapper(bo);
        func.apply(lqw);
        lqw.last("limit 0 offset 1");
        SysMemberVo entity = this.baseMapper.selectVoOne(lqw);
        if (entity == null) {
            return entity;
        }
        return fill(entity);
    }

    /**
     * 查询微信用户次数
     */
    @Override
    @Transactional(readOnly = true)
    public Long count(QueryWrapper<SysMember> wrapper) {

        wrapper.last("limit 0 offset 1");
        Long count = this.baseMapper.selectCount(wrapper);
        return count;
    }

    /**
     * 查询微信用户
     */
    @Override
    @Transactional(readOnly = true)
    public SysMemberVo getOne(QueryWrapper<SysMember> wrapper) {

        wrapper.last("limit 0 offset 1");
        SysMemberVo entity = this.baseMapper.selectVoOne(wrapper);
        if (entity == null) {
            return entity;
        }
        return fill(entity);
    }

    /**
     * 查询微信用户
     */
    @Override
    @Transactional(readOnly = true)
    public SysMemberVo getOne(SysMemberBo bo) {
        return getOne(bo, lambdaQueryWrapper -> true);
    }

    /**
     * 查询微信用户
     */
    @Override
    @Transactional(readOnly = true)
    public SysMemberVo queryById(Long memberId) {
        SysMemberVo entity = baseMapper.selectVoById(memberId);
        if (entity == null) {
            return entity;
        }
        return fill(entity);
    }


    /**
     * 查询微信用户列表
     */
    @Override
    @Transactional(readOnly = true)
    public TableDataInfo<SysMemberVo> queryPageList(SysMemberBo bo, PageQuery pageQuery) {

        return queryPageList(bo, pageQuery, lambdaQueryWrapper -> true);
    }

    /**
     * 查询微信用户列表
     */
    @Override
    @Transactional(readOnly = true)
    public TableDataInfo<SysMemberVo> queryPageList(SysMemberBo bo, PageQuery pageQuery,
                                                    Function<LambdaQueryWrapper<SysMember>, Boolean>
                                                        func) {
        LambdaQueryWrapper<SysMember> lqw = buildQueryWrapper(bo);
        func.apply(lqw);
        Page<SysMemberVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<SysMemberVo> list = result.getRecords();
        list.forEach(entity -> {
            fill(entity);
        });
        return TableDataInfo.build(result);
    }


    /**
     * 查询微信用户列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<SysMemberVo> queryList(SysMemberBo bo) {
        return queryList(bo, lambdaQueryWrapper -> true);
    }

    /**
     * 查询微信用户列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<SysMemberVo> queryList(SysMemberBo bo,
                                       Function<LambdaQueryWrapper<SysMember>, Boolean>
                                           func) {
        LambdaQueryWrapper<SysMember> lqw = buildQueryWrapper(bo);
        func.apply(lqw);
        List<SysMemberVo> list = baseMapper.selectVoList(lqw);
        if (list == null) {
            return new ArrayList<SysMemberVo>();
        }
        list.forEach(entity -> {
            fill(entity);
        });
        return list;
    }

    public SysMemberVo fill(SysMemberVo entity) {
        return entity;
    }

    private LambdaQueryWrapper<SysMember> buildQueryWrapper(SysMemberBo bo) {
        LambdaQueryWrapper<SysMember> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getName()), SysMember::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getPassword()), SysMember::getPassword, bo.getPassword());
        lqw.eq(bo.getGender() != null, SysMember::getGender, bo.getGender());
        lqw.eq(bo.getBirthday() != null, SysMember::getBirthday, bo.getBirthday());
        lqw.eq(bo.getRegisterTime() != null, SysMember::getRegisterTime, bo.getRegisterTime());
        lqw.eq(bo.getLastLoginTime() != null, SysMember::getLastLoginTime, bo.getLastLoginTime());
        lqw.eq(StringUtils.isNotBlank(bo.getLastLoginIp()), SysMember::getLastLoginIp, bo.getLastLoginIp());
        lqw.like(StringUtils.isNotBlank(bo.getNickname()), SysMember::getNickname, bo.getNickname());
        lqw.eq(StringUtils.isNotBlank(bo.getMobile()), SysMember::getMobile, bo.getMobile());
        lqw.eq(StringUtils.isNotBlank(bo.getRegisterIp()), SysMember::getRegisterIp, bo.getRegisterIp());
        lqw.eq(StringUtils.isNotBlank(bo.getHeadImgUrl()), SysMember::getHeadImgUrl, bo.getHeadImgUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getOpenId()), SysMember::getOpenId, bo.getOpenId());
        lqw.eq(StringUtils.isNotBlank(bo.getUnionId()), SysMember::getUnionId, bo.getUnionId());
        lqw.eq(StringUtils.isNotBlank(bo.getSessionKey()), SysMember::getSessionKey, bo.getSessionKey());
        lqw.eq(bo.getAuthorized() != null, SysMember::getAuthorized, bo.getAuthorized());
        lqw.eq(StringUtils.isNotBlank(bo.getAppCode()), SysMember::getAppCode, bo.getAppCode());
        lqw.eq(StringUtils.isNotBlank(bo.getCide()), SysMember::getCide, bo.getCide());
        lqw.eq(StringUtils.isNotBlank(bo.getReferee()), SysMember::getReferee, bo.getReferee());
        return lqw;
    }

    /**
     * 新增微信用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(SysMemberBo bo) {
        SysMember add = MapstructUtils.convert(bo, SysMember.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setMemberId(add.getMemberId());
        }
        return flag;
    }

    /**
     * 修改微信用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(SysMemberBo bo) {
        SysMember update = MapstructUtils.convert(bo, SysMember.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SysMember entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 删除页面
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidById(Long id, Boolean isValid) {
        return deleteWithValidByIds(CollUtil.newHashSet(id), isValid);
    }

    /**
     * 批量删除微信用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 刷新微信公众号ID
     */
    @Transactional
    public void updateMpOpenIdToMember() {
        SysAccountVo accountPublicVo = sysAccountService.getOne(new SysAccountBo().builder().appCode(AppCodeEnum.mfcapp.getPublicAppCode()).build());
        if (accountPublicVo == null) {
            throw new BusiException("当前应用没有配置微信账号");
        }
        UserAPI userAPI = new UserAPI(accountPublicVo);
        GetUsersResponse getUsersResponse = userAPI.getUsers("");
        List<UserInfo> userInfoList = new ArrayList<>();
        Arrays.stream(getUsersResponse.getData().getOpenid()).toList().forEach(s -> {
            GetUserInfoResponse getUserInfoResponse = userAPI.getUserInfo(s);
            List<SysMemberVo> list = queryList(new SysMemberBo().builder()
                .unionId(getUserInfoResponse.getUnionid()).build());
            if (list != null) {
                list.forEach(sysMemberVo -> {
                    if (sysMemberVo != null && StringUtils.isEmpty(sysMemberVo.getPublicId())) {
                        SysMemberBo sysMemberBo = new SysMemberBo();
                        sysMemberBo.setMemberId(sysMemberVo.getMemberId());
                        sysMemberBo.setUnionId(sysMemberVo.getUnionId());
                        sysMemberBo.setPublicId(getUserInfoResponse.getOpenid());
                        updateByBo(sysMemberBo);
                    }
                });

            }
        });
    }
}
